// 等待
const PEDDING = 'pedding';
// 成功
const FULFILLED = 'fulfilled';
// 失败
const REJECTED = 'rejected';

function MyPromise(executor) {
  // this.state 代表Promise的状态
  this.state = PEDDING;
  // this.value是Promise的结果值
  this.value = null;
  // this.reason是Promise的失败原因
  this.reason = null;
  // this.onFulfilledCallbacks是一个数组，用来存放回调
  this.onFulfilledCallbacks = [];
  // this.onRejectedCallbacks是一个数组，用来存放失败的回调
  this.onRejectedCallbacks = [];

  // resolve reject
  const resolve = (value) => {
    if (this.state === PEDDING) {
      this.state = FULFILLED;
      this.value = value;
      this.onFulfilledCallbacks.forEach((cb) => {
        cb();
      });
    }
  };

  const reject = (reason) => {
    if (this.state === PEDDING) {
      this.state = REJECTED;
      this.reason = reason;
      this.onRejectedCallbacks.forEach((cb) => {
        cb();
      });
    }
  };
  try {
    executor(resolve, reject);
  } catch (reason) {
    reject(reason);
  }
}
MyPromise.prototype.then = function (
  onFulfilled = (value) => value,
  onRejected = (reson) => reson
) {
  const promise2 = new MyPromise((resolve, reject) => {
    switch (this.state) {
    case PEDDING:
      // 处理的是将所有的回调收集到一起
      this.onFulfilledCallbacks.push(() => {
        setTimeout(() => {
          // 异步执行
          try {
            const x = onFulfilled(this.value);
            resolve(x);
          } catch (reason) {
            reject(reason);
          }
        },0);
      });
      this.onRejectedCallbacks.push(() => {
        setTimeout(() => {
          try {
            const x = onRejected(this.reason);
            resolve(x);
          } catch (reason) {
            reject(reason);
          }
        },0); 
      });
      break;
    case FULFILLED:
      setTimeout(()=>{
        try {
          const x = onFulfilled(this.value);
          resolve(x);
        } catch (reason) {
          reject(reason);
        }
      },0);
      break;
    case REJECTED:
      setTimeout(()=>{
        try {
          const x = onRejected(this.reason);
          resolve(x);
        } catch (reason) {
          reject(reason);
        }
      },0);
      break;
    default:
      console.log('default');
      break;
    }
  });
  return promise2;
};


// promise.catch(err=>console.log('err'));
MyPromise.prototype.catch = function(onRejected){
  return this.then(null,onRejected);
};

MyPromise.prototype.finally = function(callback){
  return this.then((value)=>{
    callback();
    return value;
  },
  reason=>{
    callback();
    throw reason;
  });
};
// 1 3 2

// 1. 构造调用
// 2. 异步调用
// 3. 链式调用

// const i = 0;
// const promise = new MyPromise((resolve, reject) => {
//   reject('失败');
// });
// promise.then(res=>{
//   console.log('成功');
// },(reason)=>console.log('失败'));

// promise.finally(res=>{
//   console.log('完成');
// });

// 实例.__proto__  === 类.prototype
MyPromise.all = function(promises){
  // 1. 返回的是promise
  return new MyPromise((resolve,reject)=>{
    // 2. 计数器 记录的是结果的数量
    let count = 0;
    const result = [];
    promises.forEach((promise,index)=>{
      promise.then((value)=>{
        result[index] = value;
        count++;
        // 3. 当count等于promises的长度时，说明所有的promise都执行完毕
        if(count === promises.length){
          // 4. 返回结果
          resolve(result);
        }
      }
      // 5. 当promise失败时，直接返回失败
      ,(reason)=>{
        reject(reason);
      });
    });
  });
};
const promise1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('promise1');
  }, 100);
});

const promise2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    // reject(new Error('error'));
  }, 500);
});

const promise3= new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('promise3');
  }, 300);
});
// MyPromise.all([promise1, promise2, promise3]).then(res => {
//   console.log(res);
// }
// , reason => {
//   console.log(reason);
// });

MyPromise.allSettled = function (promises) {
  return new MyPromise((resolve, reject) => {
    let count = 0;
    const result = [];
    promises.forEach((promise, index) => {
      promise.then((value) => {
        result[index] = { status: 'fulfilled', value };
        count ++;
        if(count === promises.length){
          resolve(result);
        }
      },
      (reason) => {
        result[index] = { status: 'rejected', reason };
        count++;
        if(count === promises.length){
          resolve(result);
        }
      }
      );
    });
  });
};
MyPromise.allSettled([promise1, promise2, promise3]).then(values=>{
  console.log(values);
});

MyPromise.race = function(promises){
  return new MyPromise ((resolve,reject)=>{
    promises.forEach((promise)=>{
      promise.then(res=>{
        resolve(res);
      });
    },
    (reason)=>{
      reject(reason);
      // resolve(null);
    });
  });
};

MyPromise.race([promise1, promise2, promise3]).then(value=>{
  console.log(value);
});